143. 重排链表
143. 重排链表
Similar Question
leading to the advanced question
Solution Tips
方案一: 快慢指针找中点 + 翻转后半段 + 合并链表
var reorderList = function(head) {
if (head === null || head.next === null) return head;
const dummy = new Node(0);
dummy.next = head;
// 找到链表中点
let prevSlow = dummy;
let slow = head;
let fast = head;
while (fast !== null && fast.next !==null) {
fast = fast.next.next;
slow = slow.next;
prevSlow = prevSlow.next;
}
// 断开
let prev = null;
let cur = slow;
prevSlow.next = null;
// 翻转后半段
while (cur !== null) {
const next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
// 然后 merge
let l1 = head;
let l2 = prev;
while (l2 !== null) {
const next = l1.next;
l1.next = l2;
l1 = l2;
l2 = next;
}
return dummy.next;
};
方案二: 双向链表 + 原地重排
var reorderList = function(head) {
// 复制一个链表, 然后翻转, 然后根据中点截断, 可以写一写
// 第一次遍历, 构造出双向链表, 遍历到最后一个节点之后, 反过来拼接, 下一个和前一个相等, 就结束
const dummy = new Node(0);
dummy.next = head;
// 构造出双向链表
let prev = dummy;
let cur = head;
while (cur !== null) {
cur.prev = prev;
prev = cur;
cur = cur.next;
}
// 遍历完之后 prev 在最后一个节点上
let high = prev;
let low = head;
// 奇数个节点 和 偶数个节点 结束的条件不同
while (high !== low && high !== low.next) {
const next = low.next;
low.next = high;
high = high.prev;
low.next.next = next;
low = next;
}
// 断开环
high.next = null;
return dummy.next;
};
方案三: 数组
先转换成数组, 然后按照指定顺序访问节点, 重新拼接即可
指针 i
从头向尾,指针 j
从尾向头,重新组装链表